#include <ctype.h>
#include <sqlite3.h>
#include <json-c/json.h>

#include <srclink/utils.h>
#include <webhttpd/HttpResponse.h>


// MIME 类型映射
const char *get_mime_type(const char *filepath) {
    const char *ext = strrchr(filepath, '.');
    if (!ext) return "application/octet-stream"; // 默认二进制类型

    if (strcmp(ext, ".html") == 0 || strcmp(ext, ".htm") == 0) {
        return "text/html; charset=utf-8";
    } else if (strcmp(ext, ".css") == 0) {
        return "text/css; charset=utf-8";
    } else if (strcmp(ext, ".js") == 0) {
        return "application/javascript; charset=utf-8";
    } else if (strcmp(ext, ".jpg") == 0 || strcmp(ext, ".jpeg") == 0) {
        return "image/jpeg";
    } else if (strcmp(ext, ".png") == 0) {
        return "image/png";
    } else if (strcmp(ext, ".webp") == 0) {
        return "image/webp";
    } else {
        return "application/octet-stream"; // 未知类型
    }
}


GList *query_to_dict_list(sqlite3 *db, const char *sql_query) {
    sqlite3_stmt *stmt;
    GList *list = NULL;

    // 准备 SQL 查询
    int rc = sqlite3_prepare_v2(db, sql_query, -1, &stmt, NULL);
    if (rc != SQLITE_OK) {
        fprintf(stderr, "Failed to prepare statement: %s\n", sqlite3_errmsg(db));
        return NULL;
    }

    // 遍历查询结果
    while ((rc = sqlite3_step(stmt)) == SQLITE_ROW) {
        GHashTable *row_dict = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);

        int column_count = sqlite3_column_count(stmt);
        for (int i = 0; i < column_count; i++) {
            const char *column_name = sqlite3_column_name(stmt, i); // 获取字段名
            const char *column_value = (const char *) sqlite3_column_text(stmt, i); // 获取字段值

            if (column_value == NULL) {
                column_value = ""; // 如果值为 NULL，存储为空字符串
            }

            // 插入到 GHashTable 中，键和值都需要复制
            g_hash_table_insert(row_dict, g_strdup(column_name), g_strdup(column_value));
        }

        // 将当前行的字典添加到 GList
        list = g_list_append(list, row_dict);
    }

    // 清理 SQLite 语句
    sqlite3_finalize(stmt);

    return list;
}

GList *stmt_to_dict_list(sqlite3_stmt *stmt) {
    GList *list = NULL;

    // 遍历查询结果
    while (sqlite3_step(stmt) == SQLITE_ROW) {
        GHashTable *row_dict = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);

        int column_count = sqlite3_column_count(stmt);
        for (int i = 0; i < column_count; i++) {
            const char *column_name = sqlite3_column_name(stmt, i); // 获取字段名
            const char *column_value = (const char *) sqlite3_column_text(stmt, i); // 获取字段值

            if (column_value == NULL) {
                column_value = ""; // 如果值为 NULL，存储为空字符串
            }

            // 插入到 GHashTable 中，键和值都需要复制
            g_hash_table_insert(row_dict, g_strdup(column_name), g_strdup(column_value));
        }

        // 将当前行的字典添加到 GList
        list = g_list_append(list, row_dict);
    }

    return list;
}


// 打印 GList 中的 GHashTable 数据
void print_dict_list(GList *list) {
    for (GList *l = list; l != NULL; l = l->next) {
        GHashTable *row_dict = (GHashTable *) l->data;

        GList *keys = g_hash_table_get_keys(row_dict);
        for (GList *k = keys; k != NULL; k = k->next) {
            const char *key = (const char *) k->data;
            const char *value = (const char *) g_hash_table_lookup(row_dict, key);
            printf("%s: %s\n", key, value);
        }
        g_list_free(keys);
        printf("\n");
    }
}

// 释放 GList 中的 GHashTable 数据
void free_dict_list(GList *list) {
    g_list_free_full(list, (GDestroyNotify) g_hash_table_destroy);
}

// 函数：将 GHashTable 转换为 JSON 对象
struct json_object *g_hash_table_to_json_object(GHashTable *hash_table) {
    struct json_object *json_obj = json_object_new_object();

    // 获取 GHashTable 的所有键
    GList *keys = g_hash_table_get_keys(hash_table);

    // 遍历键并添加到 JSON 对象
    for (GList *key_item = keys; key_item != NULL; key_item = key_item->next) {
        const char *key = (const char *) key_item->data;
        const char *value = (const char *) g_hash_table_lookup(hash_table, key);

        // 添加键值对到 JSON 对象
        json_object_object_add(json_obj, key, json_object_new_string(value));
    }

    // 释放键列表
    g_list_free(keys);

    return json_obj;
}

// 函数：将 GList 转换为 JSON 数组
struct json_object *g_list_to_json_array(GList *list) {
    struct json_object *json_array = json_object_new_array();

    // 遍历 GList，转换每个 GHashTable
    for (GList *item = list; item != NULL; item = item->next) {
        GHashTable *hash_table = (GHashTable *) item->data;

        // 转换 GHashTable 为 JSON 对象
        struct json_object *json_obj = g_hash_table_to_json_object(hash_table);

        // 添加 JSON 对象到 JSON 数组
        json_object_array_add(json_array, json_obj);
    }

    return json_array;
}

// URL 解码函数
char *url_decode(const char *str) {
    char *decoded = malloc(strlen(str) + 1);
    char *p = decoded;

    for (size_t i = 0; str[i] != '\0'; i++) {
        if (str[i] == '%') {
            if (isxdigit(str[i + 1]) && isxdigit(str[i + 2])) {
                char hex[3] = {str[i + 1], str[i + 2], '\0'};
                *p++ = (char) strtol(hex, NULL, 16);
                i += 2;
            }
        } else if (str[i] == '+') {
            *p++ = ' '; // '+' 转为空格
        } else {
            *p++ = str[i];
        }
    }
    *p = '\0';
    return decoded;
}

// 解析查询参数到 GHashTable
GHashTable *parse_query_string(const char *query) {
    GHashTable *dict = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);

    char *query_copy = strdup(query); // 复制查询字符串，避免修改原字符串
    char *pair = query_copy;

    while (pair && *pair) {
        char *key = pair;
        char *value = strchr(pair, '=');

        if (value) {
            *value = '\0'; // 将 '=' 替换为字符串结束符
            value++;
        } else {
            value = ""; // 如果没有值，将其视为空字符串
        }

        // 查找下一个键值对
        pair = strchr(value, '&');
        if (pair) {
            *pair = '\0'; // 将 '&' 替换为字符串结束符
            pair++;
        }

        // URL 解码并插入到哈希表
        char *decoded_key = url_decode(key);
        char *decoded_value = url_decode(value);
        g_hash_table_insert(dict, g_strdup(decoded_key),g_strdup(decoded_value));
    }

    free(query_copy);
    return dict;
}

// 打印 GHashTable 内容
void print_g_hash_table(GHashTable *dict) {
    GList *keys = g_hash_table_get_keys(dict);
    for (GList *iter = keys; iter != NULL; iter = iter->next) {
        char *key = (char *) iter->data;
        char *value = (char *) g_hash_table_lookup(dict, key);
        printf("%s: %s\n", key, value);
    }
    g_list_free(keys);
}

// 快速解析 query 参数，返回 glib 对象地址，如果没有 query 就返回 NULL
GHashTable *parse_querys(char *path) {
    char *query = strchr(path, '?');
    if (query) {
        query++;
        GHashTable *dict = parse_query_string(query);
        return dict;
    }
    return NULL;
}


json_object *normal_api_json(int code, char *msg) {
    json_object *response_json = json_object_new_object();
    json_object_object_add(response_json, "code", json_object_new_int(code));
    json_object_object_add(response_json, "msg", json_object_new_string(msg));
    return response_json;
}

json_object *data_api_json(int code, char *msg, int count, json_object *data_array) {
    json_object *response_json = json_object_new_object();
    json_object_object_add(response_json, "code", json_object_new_int(code));
    json_object_object_add(response_json, "msg", json_object_new_string(msg));
    json_object_object_add(response_json, "count", json_object_new_int(count));
    json_object_object_add(response_json, "data", data_array);
    return response_json;
}

HttpResponse normal_response(int status_code, int code, char *msg) {
    HttpResponse response;

    response.status_code = status_code;
    response.headers = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
    g_hash_table_insert(response.headers, g_strdup("Content-Type"), g_strdup("application/json; charset=utf-8"));

    char *json_string = (char *)json_object_to_json_string_ext(
        normal_api_json(code, msg),
        JSON_C_TO_STRING_PRETTY);

    response.body.content = malloc(strlen(json_string) + 1);
    response.body.size = strlen(json_string);
    strcpy(response.body.content, json_string);

    free(json_string);

    return response;
}
